package com.yyfax.pay.order.data.service.impl;

import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;

import com.yyfax.commons.lang.BeanUtil;
import com.yyfax.commons.lang.DateUtil;
import com.yyfax.framework.common.Log;
import com.yyfax.framework.service.CacheService;
import com.yyfax.framework.service.SequenceService;
import com.yyfax.framework.service.impl.BaseServiceImpl;
import com.yyfax.framework.yyfax.CryptUtil;
import com.yyfax.framework.yyfax.DesensitizationUtil;
import com.yyfax.framework.yyfax.enums.IdCardTypeEnum;
import com.yyfax.framework.yyfax.enums.SequenceStrategy;
import com.yyfax.framework.yyfax.enums.YesNoEnum;
import com.yyfax.pay.common.enums.PayRspCodeEnum;
import com.yyfax.pay.common.exception.YYPayException;
import com.yyfax.pay.config.data.service.BankConfigService;
import com.yyfax.pay.order.data.dao.UserAuthDao;
import com.yyfax.pay.order.data.service.UserAuthService;
import com.yyfax.pay.order.data.service.UserPaymentService;
import com.yyfax.pay.order.model.po.UserAuthPO;
import com.yyfax.pay.order.model.po.UserPaymentPO;
import com.yyfax.pay.order.model.vo.UserAuthVO;
import com.yyfax.pay.order.model.vo.UserPaymentVO;

/**
 * 用户认证信息服务实现
 *
 * @author buyi
 * @date 2017-04-12 11:09:15
 * @since 1.0.0
 */
@Service
public class UserAuthServiceImpl extends BaseServiceImpl implements UserAuthService {
	private Logger logger = LoggerFactory.getLogger(getClass());

	@Autowired
	private UserAuthDao userAuthDao;

	@Autowired
	private SequenceService sequenceService; // 序列号生成服务

	@Autowired
	private UserPaymentService userPaymentService;

	@Autowired
	private BankConfigService bankConfigService;

	public UserAuthServiceImpl(@Qualifier("payCacheService") CacheService cacheService) {
		super(cacheService);
	}

	@Override
	public UserAuthPO queryByIdAndMerchantCode(int id, String merchantCode) throws Exception {
		if (id <= 0 && StringUtils.isBlank(merchantCode)) {
			logger.debug("参数 'id' 不能为0，且 'merchantCode' 不能为空 ");
			return null;
		}

		return userAuthDao.selectByIdAndMerchantCode(id, merchantCode);
	}

	@Override
	public UserAuthPO queryByUserIdAndMerchantCode(String userId, String merchantCode) {
		if (StringUtils.isBlank(userId) && StringUtils.isBlank(merchantCode)) {
			logger.debug("参数 'id' 不能为0，且 'merchantCode' 不能为空 ");
		}

		return userAuthDao.selectByUserIdAndMerchantCode(userId, merchantCode);
	}

	@Override
	public UserAuthPO queryByMerchanCodeAndIdNo(String merchantCode, String idNo) throws Throwable {
		if (StringUtils.isBlank(merchantCode) && StringUtils.isBlank(idNo)) {
			logger.debug("参数 'id' 不能为0，且 'merchantCode' 不能为空 ");
		}

		return userAuthDao.selectByMerchanCodeAndIdNo(merchantCode, CryptUtil.encrypt(idNo));
	}

	@Override
	public String saveAndReturnUserAuthId(UserAuthPO po) throws Exception {
		if (po == null) {
			logger.debug("参数po为空，返回-1");
			return null;
		}

		// UserAuthPO userAuthPO = queryByUserIdAndMerchantCode(po.getUserId(), po.getMerchantCode());
		// if (userAuthPO != null) {
		// logger.error("商户：{}，用户：{}实名认证信息已存在");
		// return null;
		// }

		String userAuthId = sequenceService.sequenceStr(SequenceStrategy.PAY_USER); // 根据策略生成业务主键

		po.setUserAuthId(userAuthId);
		po.setCreateTime(DateUtil.getCurrentDateTime());
		po.setState(YesNoEnum.YES.getValue());

		int id = userAuthDao.insert(po);
		if (id > 0) {
			po.setId(id);
		}

		return userAuthId;
	}

	@Override
	public UserAuthVO queryUserAuthVO(String merchantCode, String userId) throws Exception {
		UserAuthVO userAuthVO = new UserAuthVO();

		UserAuthPO userAuthPO = queryByUserIdAndMerchantCode(userId, merchantCode);
		if (userAuthPO == null) {
			return null;
		}

		BeanUtils.copyProperties(userAuthPO, userAuthVO);

		List<UserPaymentPO> userPaymentPOs = userPaymentService.queryListByUserIdAndMerchantCode(userId, merchantCode);
		List<UserPaymentVO> userPaymentVOs = new ArrayList<>();
		if (userPaymentPOs != null) {
			for (UserPaymentPO userPaymentPO : userPaymentPOs) {
				if (YesNoEnum.YES.isValue(userPaymentPO.getState())) {
					UserPaymentVO userPaymentVO = new UserPaymentVO();

					BeanUtil.copyProperties(userPaymentPO, userPaymentVO);
					userPaymentVO.setBankEnName(bankConfigService.queryByBankCode(userPaymentVO.getBankCode()).getEnName());
					userPaymentVO.setIdNoCip(userAuthPO.getIdNoCip());
					userPaymentVO.setName(userAuthPO.getName());

					userPaymentVOs.add(userPaymentVO);
				}
			}
		}

		userAuthVO.setUserPaymentVOs(userPaymentVOs);

		return userAuthVO;
	}

	@Override
	public boolean checkUserOpenSuccess(String merchantCode, String userId, String name, String idNoCip, String cardNoCip, String phone) {

		UserAuthPO userAuthPO = null;
		try {
			userAuthPO = userAuthDao.selectByFourElements(merchantCode, userId, name, idNoCip, cardNoCip, name);
		} catch (Throwable throwable) {
			logger.warn(Log.op("UserAuthServiceImpl.checkUserOpenSuccess").toString(), throwable);
		}

		if (userAuthPO != null) {
			return true;
		} else {
			return false;
		}
	}

	@Override
	public int insert(UserAuthPO userAuthPO) {
		if (null == userAuthPO){
			return -1;
		}
		userAuthPO.setCreateTime(DateUtil.getCurrentDateTime());
		return userAuthDao.insert(userAuthPO);
	}

	@Override
	public void checkIdNoAndName(String merchantCode, String userId, String idNo, String name) throws Throwable {
		if (StringUtils.isBlank(idNo)) {
			return;
		}

		// 判断如果传参带身份证号，则检验身份证号一致性,以及身份证是否已经被使用
		UserAuthPO userAuthPO = this.queryByMerchanCodeAndIdNo(merchantCode, idNo);
		if (userAuthPO != null && !StringUtils.equals(userAuthPO.getUserId(), userId)) {
			// 如果存在相应实名认证信息，且非当前用户，则抛出异常
			throw new YYPayException(PayRspCodeEnum.PAY_CODE_ID_NO_ERROR, "身份证号：" + idNo + "已经被使用", "该身份证已绑定其他账号");
		}

		String idNoCip = CryptUtil.encrypt(idNo);
		UserAuthPO currUserAuthPO = this.queryByUserIdAndMerchantCode(userId, merchantCode);
		if (currUserAuthPO != null) {
			// 如果存在当前用户实名认证信息，且证件号不一致
			// 如果证件号不一致，或者姓名不一致
			if (!StringUtils.equals(currUserAuthPO.getIdNoCip(), idNoCip) || !StringUtils.equals(currUserAuthPO.getName(), name)) {
				throw new YYPayException(PayRspCodeEnum.PAY_CODE_ID_NO_ERROR,
						"用户：" + currUserAuthPO.getUserAuthId() + " 存在实名认证信息身份证号不一致，或者姓名一致，参数：" + idNo, "身份信息有误");
			}
		}
	}

	@Override
	public int save(String merchantCode, String userId, String idNo, String name, String paymentCode, String bankCode, String bankName, String cardNo,
			String phone, String userPaymentExt) throws Throwable {
		String idNoCip = CryptUtil.encrypt(idNo);
		String cardNoCip = CryptUtil.encrypt(cardNo);
		boolean isUserAuthDuplicate = false;

		// 判断用户实名信息是否存在，如果已经存在实名信息，则判断身份证号是否一致
		UserAuthPO userAuthPO = this.queryByUserIdAndMerchantCode(userId, merchantCode);
		if (userAuthPO != null && !StringUtils.equals(idNoCip, userAuthPO.getIdNoCip())) {
			// 如果实名信息存在，身份证号不一致，则异常
			logger.error("商户：{}，用户：{}实名认证信息已存在", merchantCode, userId);
			return -1;
		}

		if (userAuthPO == null) {
			// 如果实名信息不存在，则保存信息
			userAuthPO = new UserAuthPO();
			userAuthPO.setMerchantCode(merchantCode);
			userAuthPO.setUserId(userId);
			userAuthPO.setIdNo(DesensitizationUtil.convertIdCard(idNo));
			userAuthPO.setIdNoCip(idNoCip);
			userAuthPO.setIdType(IdCardTypeEnum.PRC_ID.getValue());
			userAuthPO.setName(name);
			userAuthPO.setState(YesNoEnum.YES.getValue());

			try {
				saveAndReturnUserAuthId(userAuthPO);
			} catch (DuplicateKeyException e) {
				// 在并发的情况可能存在身份证重复的场景，需要判断身份证是否一致
				logger.warn("商户：{}，用户：{},身份证：{}保存实名认证信息，主键冲突", merchantCode, userId, idNoCip);
				isUserAuthDuplicate = true;
			}
		}

		if (isUserAuthDuplicate) {
			// 保存用户实名信息出现主键冲突
			// 并发的情况可能存在身份证重复的场景，需要判断身份证是否一致

			userAuthPO = this.queryByUserIdAndMerchantCode(userId, merchantCode);
			if (userAuthPO == null) {
				// 没有找相应商户的用户信息，则抛出异常
				logger.error("保存实名鉴权信息出现主键冲突,存在已经实名鉴权信息,或者身份证已被使用，需要运维跟踪问题,merchantCode:{},userId:{},idNoCip:{}", merchantCode, userId, idNoCip);
				return -1;
			}

			if (!StringUtils.equals(idNoCip, userAuthPO.getIdNoCip())) {
				// 如果实名信息存在，身份证号不一致，则异常
				logger.error("保存实名鉴权信息出现主键冲突,存在已经实名鉴权信息,身份证不一致已被使用，需要运维跟踪问题,merchantCode:{},userId:{},idNoCip:{}", merchantCode, userId, idNoCip);
				return -1;
			}
		}

		// 判断用户支付认证信息
		UserPaymentPO paymentPO = userPaymentService.query(merchantCode, userId, paymentCode);
		if (paymentPO != null && YesNoEnum.YES.isValue(paymentPO.getState())) {// 支付通道信息
			logger.warn("商户：{}，用户：{}，支付通道：{}，存在有效的支付认证信息，不做操作", merchantCode, userId, paymentCode);
			return -1;
		}

		UserPaymentPO userPaymentPO = new UserPaymentPO();
		BeanUtils.copyProperties(userAuthPO, userPaymentPO);
		userPaymentPO.setUserAuthId(userAuthPO.getUserAuthId());
		userPaymentPO.setPaymentCode(paymentCode);
		userPaymentPO.setBankCode(bankCode);
		userPaymentPO.setBankName(bankName);
		userPaymentPO.setCardNo(DesensitizationUtil.convertBankCard(cardNo));
		userPaymentPO.setCardNoCip(cardNoCip);
		userPaymentPO.setPhone(phone);
		userPaymentPO.setExt(userPaymentExt);
		userPaymentPO.setState(YesNoEnum.YES.getValue());

		if (paymentPO == null) {
			try {
				userPaymentService.save(userPaymentPO);
			} catch (DuplicateKeyException e) {
				logger.error("保存支付鉴权信息出现主键冲突,存在支付鉴权信息，需要运维跟踪问题,merchantCode:{},userId:{},paymentCode:{}", merchantCode, userId, paymentCode);
				return -1;
			}
		} else {
			userPaymentService.modify(userPaymentPO);
		}

		return 1;
	}
}
